﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

namespace vJine.Core.IoC {
    public class Reflect {
        #region Types

        public static readonly Type @void = typeof(void);

        public static readonly Type @bool = typeof(bool);

        public static readonly Type @sbyte = typeof(sbyte);
        public static readonly Type @byte = typeof(byte);
        public static readonly Type @char = typeof(char);
        public static readonly Type @short = typeof(short);
        public static readonly Type @ushort = typeof(ushort);
        public static readonly Type @int = typeof(int);
        public static readonly Type @uint = typeof(uint);
        public static readonly Type @long = typeof(long);
        public static readonly Type @ulong = typeof(ulong);
        public static readonly Type @float = typeof(float);
        public static readonly Type @double = typeof(double);
        public static readonly Type @decimal = typeof(decimal);

        public static readonly Type @string = typeof(string);
        public static readonly Type @guid = typeof(Guid);

        public static readonly Type @DateTime = typeof(DateTime);

        public static readonly Type @object = typeof(object);
        public static readonly Type @type = typeof(Type);

        public static readonly Type @boolNull = typeof(bool?);
        public static readonly Type @sbyteNull = typeof(sbyte?);
        public static readonly Type @byteNull = typeof(byte?);
        public static readonly Type @charNull = typeof(char?);
        public static readonly Type @shortNull = typeof(short?);
        public static readonly Type @ushortNull = typeof(ushort?);
        public static readonly Type @intNull = typeof(int?);
        public static readonly Type @uintNull = typeof(uint?);
        public static readonly Type @longNull = typeof(long?);
        public static readonly Type @ulongNull = typeof(ulong?);
        public static readonly Type @floatNull = typeof(float?);
        public static readonly Type @doubleNull = typeof(double?);
        public static readonly Type @decimalNull = typeof(decimal?);
        public static readonly Type @DateTimeNull = typeof(DateTime?);

        public static readonly Type @boolArray = typeof(bool[]);
        public static readonly Type @sbyteArray = typeof(sbyte[]);
        public static readonly Type @byteArray = typeof(byte[]);
        public static readonly Type @shortArray = typeof(short[]);
        public static readonly Type @ushortArray = typeof(ushort[]);
        public static readonly Type @intArray = typeof(int[]);
        public static readonly Type @uintArray = typeof(uint[]);
        public static readonly Type @longArray = typeof(long);
        public static readonly Type @ulongArray = typeof(ulong[]);
        public static readonly Type @floatArray = typeof(float[]);
        public static readonly Type @doubleArray = typeof(double[]);
        public static readonly Type @decimalArray = typeof(decimal[]);
        public static readonly Type @DateTimeArray = typeof(DateTime[]);
        public static readonly Type @stringArray = typeof(string[]);
        public static readonly Type @objectArray = typeof(object[]);

        public static readonly Type @boolRef = typeof(bool).MakeByRefType();
        public static readonly Type @sbyteRef = typeof(sbyte).MakeByRefType();
        public static readonly Type @byteRef = typeof(byte).MakeByRefType();
        public static readonly Type @shortRef = typeof(short).MakeByRefType();
        public static readonly Type @ushortRef = typeof(ushort).MakeByRefType();
        public static readonly Type @intRef = typeof(int).MakeByRefType();
        public static readonly Type @uintRef = typeof(uint).MakeByRefType();
        public static readonly Type @longRef = typeof(long).MakeByRefType();
        public static readonly Type @ulongRef = typeof(ulong).MakeByRefType();
        public static readonly Type @floatRef = typeof(float).MakeByRefType();
        public static readonly Type @doubleRef = typeof(double).MakeByRefType();
        public static readonly Type @decimalRef = typeof(decimal).MakeByRefType();
        public static readonly Type @DateTimeRef = typeof(DateTime).MakeByRefType();
        public static readonly Type @stringRef = typeof(string).MakeByRefType();
        public static readonly Type @objectRef = typeof(object).MakeByRefType();

        public static readonly Type @IDisposable = typeof(IDisposable);

        public static readonly Type @Stream = typeof(Stream);
        public static readonly Type @StreamRef = typeof(Stream).MakeByRefType();

        public static Dictionary<string, Type> BaseTypes;

        static void Init_Types() {
            Reflect.BaseTypes = new Dictionary<string, Type>();

            Reflect.BaseTypes.Add("bool", @bool); Reflect.BaseTypes.Add("Boolean", @bool);
            Reflect.BaseTypes.Add("sbyte", @sbyte); Reflect.BaseTypes.Add("SByte", @sbyte); 
            Reflect.BaseTypes.Add("byte", @byte); Reflect.BaseTypes.Add("Byte", @byte);
            Reflect.BaseTypes.Add("short", @short); Reflect.BaseTypes.Add("Int16", @short);
            Reflect.BaseTypes.Add("ushort", @ushort); Reflect.BaseTypes.Add("UInt16", @ushort);
            Reflect.BaseTypes.Add("int", @int); Reflect.BaseTypes.Add("Int32", @int);
            Reflect.BaseTypes.Add("uint", @uint); Reflect.BaseTypes.Add("UInt32", @uint);
            Reflect.BaseTypes.Add("long", @long); Reflect.BaseTypes.Add("Int64", @long);
            Reflect.BaseTypes.Add("ulong", @ulong); Reflect.BaseTypes.Add("UInt64", @ulong);
            Reflect.BaseTypes.Add("float", @float); Reflect.BaseTypes.Add("Single", @float);
            Reflect.BaseTypes.Add("double", @double); Reflect.BaseTypes.Add("Double", @double);
            Reflect.BaseTypes.Add("decimal", @decimal); Reflect.BaseTypes.Add("Decimal", @decimal);
            Reflect.BaseTypes.Add("DateTime", @DateTime);

            Reflect.BaseTypes.Add("bool?", boolNull); Reflect.BaseTypes.Add("Boolean?", boolNull);
            Reflect.BaseTypes.Add("sbyte?", sbyteNull); Reflect.BaseTypes.Add("Sbyte?", sbyteNull);
            Reflect.BaseTypes.Add("byte?", byteNull); Reflect.BaseTypes.Add("Byte?", byteNull);
            Reflect.BaseTypes.Add("short?", shortNull); Reflect.BaseTypes.Add("Int16?", shortNull);
            Reflect.BaseTypes.Add("ushort?", ushortNull); Reflect.BaseTypes.Add("UInt16?", ushortNull);
            Reflect.BaseTypes.Add("int?", intNull); Reflect.BaseTypes.Add("Int32?", intNull);
            Reflect.BaseTypes.Add("uint?", uintNull); Reflect.BaseTypes.Add("UInt32?", uintNull);
            Reflect.BaseTypes.Add("long?", longNull); Reflect.BaseTypes.Add("Int64?", longNull);
            Reflect.BaseTypes.Add("ulong?", ulongNull); Reflect.BaseTypes.Add("UInt64?", ulongNull);
            Reflect.BaseTypes.Add("float?", floatNull); Reflect.BaseTypes.Add("Single?", floatNull);
            Reflect.BaseTypes.Add("double?", doubleNull); Reflect.BaseTypes.Add("Double?", doubleNull);
            Reflect.BaseTypes.Add("decimal?", decimalNull); Reflect.BaseTypes.Add("Decimal?", decimalNull);
            Reflect.BaseTypes.Add("DateTime?", DateTimeNull);

            Reflect.BaseTypes.Add("string", @string); Reflect.BaseTypes.Add("String", @string);

            Reflect.BaseTypes.Add("bool[]", boolArray);
            Reflect.BaseTypes.Add("sbyte[]", sbyteArray);
            Reflect.BaseTypes.Add("byte[]", byteArray);
            Reflect.BaseTypes.Add("short[]", shortArray);
            Reflect.BaseTypes.Add("ushort[]", ushortArray);
            Reflect.BaseTypes.Add("int[]", intArray);
            Reflect.BaseTypes.Add("uint[]", uintArray);
            Reflect.BaseTypes.Add("long[]", longArray);
            Reflect.BaseTypes.Add("ulong[]", ulongArray);
            Reflect.BaseTypes.Add("float[]", floatArray);
            Reflect.BaseTypes.Add("double[]", doubleArray);
            Reflect.BaseTypes.Add("decimal[]", decimalArray);
            Reflect.BaseTypes.Add("DateTime[]", DateTimeArray);
        }
        #endregion Types

        static Reflect() {
            Reflect.Init_Types();
        }

        internal static readonly BindingFlags defaultBindingFlags =
            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;

        public static bool IsSerializable(Type tObj) {
            return tObj.GetCustomAttributes(typeof(SerializableAttribute), false).Length > 0;
        }

        public static bool IsType(object obj, Type t) {
            return Reflect.GetType(obj) == t;
        }

        public static bool IsBaseType(Type tBaseType) {
            return tBaseType.IsPrimitive ||
                Reflect.IsNumber(tBaseType) ||
                tBaseType == Reflect.@string ||
                tBaseType == Reflect.@DateTime ||
                tBaseType == Reflect.@byteArray ||
                tBaseType == Reflect.@guid ||
                Reflect.IsEnum(tBaseType);
        }

        public static bool IsBaseType(string tBaseType) {
            Type tBase = Type.GetType(tBaseType);

            return Reflect.IsBaseType(tBase);
        }

        public static bool IsBaseType(object V) {
            Type tV = V.GetType();

            return Reflect.IsBaseType(tV);
        }

        public static bool IsBaseType(object V, PropertyInfo P) {
            return Reflect.IsBaseType(Reflect.GetType(V, P));
        }

        public static bool IsNullable(Type tObject) {
            if (tObject == null) {
                return false;
            }

            return Nullable.GetUnderlyingType(tObject) != null;
        }

        public static bool IsClass(object V) {
            if (V == null) {
                return false;
            }

            Type Tclass = V.GetType();

            return Tclass.IsClass;
        }

        #region GetTypes
        public static string GetTypeName(Type T) {

            Type Tbase = Nullable.GetUnderlyingType(T);
            string Name = Tbase == null ? T.Name : Tbase.Name + "?";
            if (Reflect.BaseTypes.ContainsKey(Name)) {
                return Name;
            }

            return
                Regex.Replace(T.AssemblyQualifiedName, @", Version=[^\]]+", "", RegexOptions.IgnoreCase);
        }

        public static Type GetType(string TypeName) {
            return Reflect.GetType(TypeName, true);
        }

        public static Type GetType(string TypeName, bool throwOnError) {
            if (Reflect.BaseTypes.ContainsKey(TypeName)) {
                return Reflect.BaseTypes[TypeName];
            }

            return Type.GetType(TypeName, throwOnError);
        }

        public static Type GetType(object objContext) {
            if (objContext == null) {
                return null;
            }

            return objContext.GetType();
        }

        public static Type GetType(object Context, PropertyInfo pi) {
            Type tProperty = pi.PropertyType;

            object vContext = pi.GetValue(Context, null);
            if (!object.Equals(vContext, null)) {
                tProperty = vContext.GetType();
            }

            return tProperty;
        }

        public static Type[] GetTypes(object[] Params) {
            if (Params == null || Params.Length == 0) {
                return Type.EmptyTypes;
            }

            int lenParams = Params.Length;
            Type[] T = new Type[lenParams];
            for (int i = 0; i < lenParams; i++) {
                T[i] =
                    Reflect.GetType(Params[i]);
            }

            return T;
        }

        public static Type[] GetTypes(string[] TypeNames) {
            if (TypeNames == null || TypeNames.Length == 0) {
                return Type.EmptyTypes;
            }

            Type[] Types = new Type[TypeNames.Length];
            for (int i = 0, len = TypeNames.Length; i < len; i++) {
                Types[i] = Reflect.GetType(TypeNames[i]);
            }

            return Types;
        }

        public static Type[] GetTypes(MethodBase M) {
            return Reflect.GetTypes(M.GetParameters());
        }

        public static Type[] GetTypes(ParameterInfo[] PIs) {
            Type[] T = new Type[PIs.Length];
            for (int i = 0; i < T.Length; i++) {
                T[i] = PIs[i].ParameterType;
            }

            return T;
        }
        #endregion

        #region Bool Functions

        public static bool IsBool(Type tObj) {
            if (tObj == null) {
                return false;
            }

            return
                tObj == Reflect.@bool;
        }

        public static bool IsBool(object V) {
            if (V == null) {
                return false;
            }

            return
                V.GetType() == Reflect.@bool;
        }

        public static bool IsBool(object V, PropertyInfo pi) {
            Type tProperty =
                Reflect.GetType(V, pi);

            return
                tProperty == typeof(bool) || tProperty == typeof(bool?);
        }
        #endregion Bool Functions

        #region Number Functions
        static readonly List<Type> NumberTypes =
            new List<Type>() {
                Reflect.@sbyte, Reflect.@sbyteNull,
                Reflect.@byte, Reflect.@byteNull,
                Reflect.@short, Reflect.@shortNull,
                Reflect.@ushort, Reflect.@ushortNull,
                Reflect.@int, Reflect.@intNull,
                Reflect.@uint, Reflect.@uintNull,
                Reflect.@long, Reflect.@longNull,
                Reflect.@ulong, Reflect.@ulongNull,
                Reflect.@float, Reflect.@floatNull,
                Reflect.@double, Reflect.@doubleNull,
                Reflect.@decimal, Reflect.@decimalNull
            };

        public static bool IsNumber(Type Tobj) {
            if (Tobj == null) {
                return false;
            }

            return
                Reflect.NumberTypes.Contains(Tobj);
        }

        public static bool IsNumber(object V) {
            if (V == null) {
                return false;
            }

            return
                Reflect.NumberTypes.Contains(V.GetType());
        }

        public static bool IsNumber(object V, PropertyInfo pi) {
            return
                Reflect.NumberTypes.Contains(Reflect.GetType(V, pi));
        }
        #endregion Number Functions

        #region Char Functions
        public static bool IsChar(object obj) {
            return obj is char;
        }

        public static bool IsChar(Type T_obj) {
            return T_obj == Reflect.@char;
        }
        #endregion Char Functions

        #region String Functions
        public static bool IsString(object V) {
            return V is string;
        }

        public static bool IsString(object V, PropertyInfo pi) {
            Type tProperty = Reflect.GetType(V, pi);

            return tProperty == Reflect.@string;
        }

        public static bool IsString(Type tObj) {
            return tObj == Reflect.@string;
        }
        #endregion String Functions

        #region DateTime Functions
        public static bool IsDateTime(object V) {
            if (V == null) {
                return false;
            }

            Type Tobj = V.GetType();

            return
                Tobj == Reflect.@DateTime || Tobj == Reflect.@DateTimeNull;
        }

        public static bool IsDateTime(object V, PropertyInfo pi) {
            Type Tobj =
                Reflect.GetType(V, pi);

            return
                Tobj == Reflect.@DateTime || Tobj == Reflect.@DateTimeNull;
        }

        public static bool IsDateTime(Type Tobj) {
            if (Tobj == null) {
                return false;
            }

            return Tobj == Reflect.@DateTime || Tobj == Reflect.@DateTimeNull;
        }
        #endregion DateTime Functions

        #region Enum

        public static bool IsEnum(object objContext) {
            return Reflect.IsEnum(Reflect.GetType(objContext));
        }

        public static bool IsEnum(object V, PropertyInfo P) {
            return Reflect.IsEnum(Reflect.GetType(V, P));
        }

        public static bool IsEnum(Type tContext) {
            if (tContext == null) {
                return false;
            }

            return tContext.IsEnum;
        }
        #endregion

        #region Array Functions
        public static bool IsArray(object V) {
            if (V == null) {
                return false;
            }

            Type tProperty = V.GetType();
            return Reflect.IsArray(tProperty);
        }

        public static bool IsArray(object V, PropertyInfo pi) {
            Type tProperty =
                Reflect.GetType(V, pi);

            return Reflect.IsArray(tProperty);
        }

        public static bool IsArray(Type tObj) {
            if (!tObj.IsArray) {
                return false;
            }

            return tObj.GetArrayRank() > 0;
        }
        #endregion Array Functions

        #region List Functions
        public static bool IsList(object V) {
            if (V == null) {
                return false;
            }

            if (Reflect.IsArray(V)) {
                return false;
            }

            Type tProperty = V.GetType();
            return
                tProperty.GetInterface("IList") != null;
        }

        public static bool IsList(object V, PropertyInfo pi) {
            Type tProperty =
                Reflect.GetType(V, pi);

            return !tProperty.IsArray && !object.Equals(tProperty.GetInterface("IList"), null);
        }

        public static bool IsList(Type T_obj) {
            if (Reflect.IsArray(T_obj)) {
                return false;
            }

            return T_obj.GetInterface("IList") != null;
        }
        #endregion List Functions

        #region Dictionary Functions
        public static bool IsDictionary(object V) {
            if (V == null) {
                return false;
            }

            Type tProperty = V.GetType();

            return Reflect.IsDictionary(tProperty);
        }

        public static bool IsDictionary(object V, PropertyInfo pi) {
            Type tProperty =
                            Reflect.GetType(V, pi);

            return Reflect.IsDictionary(tProperty);
        }

        public static bool IsDictionary(Type tObj) {
            return
                !object.Equals(tObj.GetInterface("IDictionary"), null);
        }
        #endregion Dictionary Functions

        public static Type[] GetGenericArgs<T>(){
            return Reflect.GetGenericArgs(typeof(T));   
        }

        public static Type[] GetGenericArgs(Type T) {
            Type _t = T;
            while (!_t.IsGenericType && _t.BaseType != Reflect.@object) {
                _t = _t.BaseType;
            }
            if (_t == Reflect.@object) {
                return Type.EmptyTypes;
            }
            return _t.GetGenericArguments();
        }

        #region GetProperty

        public static PropertyInfo GetProperty(object obj, string PropertyName) {
            if (object.Equals(obj, null)) {
                return null;
            }

            return Reflect.GetProperty(obj.GetType(), PropertyName);
        }

        public static PropertyInfo GetProperty(Type type, string PropertyName, BindingFlags pFlags) {
            return type.GetProperty(PropertyName, pFlags);
        }

        public static PropertyInfo[] GetProperties(object V) {
            return
                Reflect.GetProperties(V, BindingFlags.Public | BindingFlags.Instance);
        }

        public static PropertyInfo[] GetProperties(object V, BindingFlags pFlags, params Type[] Attributes) {
            if (V == null) {
                return new PropertyInfo[0];
            }

            PropertyInfo[] P = V.GetType().GetProperties(pFlags);
            List<PropertyInfo> lP = new List<PropertyInfo>();
            if (Attributes != null & Attributes.Length > 0) {
                for (int i = 0; i < P.Length; i++) {
                    for (int j = 0; j < Attributes.Length; j++) {
                        if (P[i].GetCustomAttributes(Attributes[j], true).Length > 0) {
                            lP.Add(P[i]);
                            break;
                        }
                    }
                }
            }

            return lP.ToArray();
        }

        public static PropertyInfo[] GetProperties<TParent>() {
            return Reflect.GetProperties<TParent>(BindingFlags.Public | BindingFlags.Instance);
        }

        public static PropertyInfo[] GetProperties<TParent>(BindingFlags pFlags) {
            return typeof(TParent).GetProperties(pFlags);
        }
        #endregion GetProperty

        #region SetProperty
        public static PropertyInfo Set(object obj, string PropertyName, object PropertyValue) {
            return Reflect.Set(
                obj,
                BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
                PropertyName,
                PropertyValue);
        }

        public static PropertyInfo Set(object obj, BindingFlags bfProperty, string PropertyName, object PropertyValue) {
            return Reflect.Set(obj, bfProperty, PropertyName, PropertyValue, null);
        }

        public static PropertyInfo Set(object obj, BindingFlags bfProperty, string PropertyName, object PropertyValue, object[] index) {
            Type Tobj = obj.GetType();
            PropertyInfo Property =
                Reflect.GetProperty(Tobj, PropertyName, bfProperty);

            Reflect.Set(obj, Property, PropertyValue, index);

            return Property;
        }

        public static void Set(object obj, PropertyInfo Property, object PropertyValue) {
            Reflect.Set(obj, Property, PropertyValue, null);
        }

        public static void Set(object obj, PropertyInfo Property, object PropertyValue, object[] index) {
            if (object.Equals(PropertyValue, null)) {
                Property.SetValue(obj, null, index);
            } else {
                Property.SetValue(
                    obj,
                    Class.Parse(PropertyValue, Property.PropertyType),
                    index);
            }
        }
        #endregion SetProperty

        #region GetAttriute

        public static bool HasAttribute(PropertyInfo Tobject, Type Tattribute, bool Inherit) {
            object[] A = Reflect.GetAttribute(Tobject, Tattribute, Inherit);
            return A != null && A.Length > 0;
        }

        public static bool HasAttribute(Property Tobject, Type Tattribute, bool Inherit) {
            object[] A = Reflect.GetAttribute(Tobject, Tattribute, Inherit);
            return A != null && A.Length > 0;
        }

        public static bool HasAttribute(Type Tobject, Type Tattribute, bool Inherit) {
            object[] A = Reflect.GetAttribute(Tobject, Tattribute, Inherit);
            return A != null && A.Length > 0;
        }

        public static object[] GetAttribute(Type Tobject, Type Tattribute, bool Inherit) {
            return Tobject.GetCustomAttributes(Tattribute, Inherit);
        }

        public static object[] GetAttribute(PropertyInfo Tobject, Type Tattribute, bool Inherit) {
            return Tobject.GetCustomAttributes(Tattribute, Inherit);
        }

        public static object[] GetAttribute(Property Tobject, Type Tattribute, bool Inherit) {
            return Tobject.This.GetCustomAttributes(Tattribute, Inherit);
        }

        public static T[] GetAttribute<T>(Type t) where T : Attribute {
            return Reflect.GetAttribute<T>(t, false);
        }

        public static T[] GetAttribute<T>(Type t, bool HasInherit) where T : Attribute {
            object[] tAttributes =
                t.GetCustomAttributes(typeof(T), HasInherit);

            return Reflect.GetAttribute<T>(tAttributes);
        }

        public static T[] GetAttribute<T>(Property p) where T : Attribute {
            return Reflect.GetAttribute<T>(p.This, false);
        }

        public static T[] GetAttribute<T>(PropertyInfo p) where T : Attribute {
            return Reflect.GetAttribute<T>(p, false);
        }

        public static T[] GetAttribute<T>(PropertyInfo p, bool HasInherit) where T : Attribute {
            object[] pAttributes =
                p.GetCustomAttributes(typeof(T), HasInherit);

            return Reflect.GetAttribute<T>(pAttributes);
        }

        public static T[] GetAttribute<T>(ParameterInfo p) where T : Attribute {
            return Reflect.GetAttribute<T>(p.GetCustomAttributes(typeof(T), false));
        }

        public static T[] GetAttribute<T>(ParameterInfo p, bool HasInherit) where T : Attribute {
            return Reflect.GetAttribute<T>(p.GetCustomAttributes(typeof(T), HasInherit));
        }

        private static T[] GetAttribute<T>(object[] Attributes) where T : Attribute {
            T[] attReturns = new T[Attributes.Length];
            for (int i = 0; i < Attributes.Length; i++) {
                attReturns[i] = Attributes[i] as T;
            }

            return attReturns;
        }
        #endregion GetAttribute

        #region Get Member

        public static ConstructorInfo GetCtor<Tobj>(params Type[] Tparams) {
            return Reflect.GetCtor(typeof(Tobj), Tparams);
        }

        public static ConstructorInfo GetCtor(Type Tobj, params Type[] Tparams) {
            return Tobj.GetConstructor(Tparams);
        }

        public static FieldInfo GetField<Tobj>(string Name) {
            return Reflect.GetField(typeof(Tobj), Name);
        }

        public static FieldInfo GetField(Type tObj, string Name) {
            return tObj.GetField(Name, Reflect.defaultBindingFlags);
        }

        public static PropertyInfo GetProperty<Tobj>(string Name) {
            return Reflect.GetProperty(typeof(Tobj), Name);
        }

        public static PropertyInfo GetProperty(Type tObj, string Name) {
            return tObj.GetProperty(Name, Reflect.defaultBindingFlags);
        }

        public static MethodInfo GetMethod<Tobj>(string Name, params Type[] Tparams) {
            return Reflect.GetMethod(typeof(Tobj), Name, Tparams);
        }

        public static MethodInfo GetMethod(Type tObj, string Name, params Type[] Tparams) {
            if (Tparams == null) {
                return tObj.GetMethod(Name, Reflect.defaultBindingFlags);
            } else {
                return tObj.GetMethod(Name, Reflect.defaultBindingFlags, null, Tparams, null);
            }
        }

        public static EventInfo GetEvent<Tobj>(string Name) {
            return Reflect.GetEvent(typeof(Tobj), Name);
        }

        public static EventInfo GetEvent(Type tObj, string Name) {
            return tObj.GetEvent(Name, Reflect.defaultBindingFlags);
        }
        #endregion Get Member

        #region Additional Helper
        static Type[] Signature_GetCustomAttributes = new Type[] { typeof(Type), typeof(bool) };
        static List<T> GetByAttribute<Tparent, T>(Tparent parent, T[] A, Type tAttribute, bool Inherit) {
            MethodInfo mGetCustomAttributes =
                typeof(T).GetMethod("GetCustomAttributes", Reflect.Signature_GetCustomAttributes);

            List<T> L = new List<T>();
            foreach (T a in A) {
                object[] objA =
                    mGetCustomAttributes.Invoke(a, new object[] { tAttribute, Inherit }) as object[];
                if (objA != null && objA.Length > 0) {
                    L.Add(a);
                }
            }

            return L;
        }

        public static List<Assembly> GetAssembliesByAttribute(AppDomain domain, Type tAttribute) {
            return
                Reflect.GetByAttribute<AppDomain, Assembly>(
                    domain, domain.GetAssemblies(), tAttribute, true
                    );
        }

        public static List<Type> GetTypesByAttribute(Assembly assembly, Type tAttribute) {
            return Reflect.GetByAttribute<Assembly, Type>(
                    assembly, assembly.GetTypes(), tAttribute, true
                    );
        }

        public static List<ConstructorInfo> GetConstructorsByAttribute(Type tOfConstructor, Type tAttribute) {
            return
                Reflect.GetByAttribute<Type, ConstructorInfo>(
                    tOfConstructor, tOfConstructor.GetConstructors(), tAttribute, true
                    );
        }

        public static List<FieldInfo> GetFieldsByAttribute<Tobj>(Type tAttribute) {
            return Reflect.GetFieldsByAttribute(typeof(Tobj), tAttribute);
        }

        public static List<FieldInfo> GetFieldsByAttribute(Type tOfFields, Type tAttribute) {
            return Reflect.GetByAttribute<Type, FieldInfo>(
                tOfFields, tOfFields.GetFields(), tAttribute, true
                );
        }

        public static List<PropertyInfo> GetPropertiesByAttribute<Tobj>(Type tAttribute) {
            return
                Reflect.GetPropertiesByAttribute(typeof(Tobj), tAttribute);
        }

        public static List<PropertyInfo> GetPropertiesByAttribute(Type tOfProperties, Type tAttribute) {
            return
                Reflect.GetByAttribute<Type, PropertyInfo>(
                    tOfProperties, tOfProperties.GetProperties(), tAttribute, true
                    );
        }

        public static List<MethodInfo> GetMethodsByAttribute(Type tOfMethods, Type tAttribute) {
            return
                Reflect.GetByAttribute<Type, MethodInfo>(
                    tOfMethods, tOfMethods.GetMethods(), tAttribute, true
                    );
        }

        public static List<EventInfo> GetEventsByAttribute(Type tOfEvents, Type tAttribute) {
            return
                Reflect.GetByAttribute<Type, EventInfo>(
                    tOfEvents, tOfEvents.GetEvents(), tAttribute, true
                    );
        }
        #endregion
    }
}
